package com.sac.common.utils;

import com.jcraft.jsch.*;
import com.sac.common.config.BootdoConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.util.FileCopyUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.Properties;
import java.util.Vector;

/**
 * @author xiaodong
 * @title
 * @date 2018/11/19 15:30
 * @desc
 */
@Component
@ConfigurationProperties
public class SftpUtil {

    private static BootdoConfig bootdoConfig;

    private ChannelSftp sftp;

    private Session session;
    /**
     * SFTP 登录用户名
     */
    private String username;
    /**
     * SFTP 登录密码
     */
    private String password;
    /**
     * 私钥
     */
    private String privateKey;
    /**
     * SFTP 服务器地址IP地址
     */
    private String host;
    /**
     * SFTP 端口
     */
    private int port;

    @Autowired
    public void setBootdoConfig(BootdoConfig bootdoConfig) {
        SftpUtil.bootdoConfig = bootdoConfig;
    }

    /**
     * 构造基于密码认证的sftp对象
     */
    public SftpUtil(String username, String password, String host, int port) {
        this.username = username;
        this.password = password;
        this.host = host;
        this.port = port;
    }

    /**
     * 构造基于秘钥认证的sftp对象
     */
    public SftpUtil(String username, String host, int port, String privateKey) {
        this.username = username;
        this.host = host;
        this.port = port;
        this.privateKey = privateKey;
    }

    public SftpUtil() {
    }


    /**
     * 连接sftp服务器
     */
    public void login() throws Exception {
        JSch jsch = new JSch();
        if (privateKey != null) {
            jsch.addIdentity(privateKey);// 设置私钥
        }

        session = jsch.getSession(username, host, port);
        UserInfo ui = new MyUserInfo("CarPhotograph");
        session.setUserInfo(ui);
        if (password != null) {
            session.setPassword(password);
        }
        Properties config = new Properties();
        config.put("StrictHostKeyChecking", "no");
        //TODO 移除kerberos验证方法
        config.put("PreferredAuthentications", "publickey,keyboard-interactive,password");

        session.setConfig(config);
        session.connect();

        Channel channel = session.openChannel("sftp");
        channel.connect();

        sftp = (ChannelSftp) channel;

    }

    /**
     * 关闭连接 server
     */
    public void logout() {
        if (sftp != null) {
            if (sftp.isConnected()) {
                sftp.disconnect();
            }
        }
        if (session != null) {
            if (session.isConnected()) {
                session.disconnect();
            }
        }
    }


    /**
     * 将输入流的数据上传到sftp作为文件。文件完整路径=basePath+directory
     *
     * @param path     上传到该目录
     * @param fileName sftp端文件名
     * @param input    输入流
     */
    public void upload(String path, String fileName, InputStream input) throws SftpException {
        try {
            sftp.cd(path);
        } catch (SftpException e) {
            //目录不存在，则创建文件夹
            String[] dirs = path.split("/");
            for (String dir : dirs) {
                if (null == dir || "".equals(dir)) continue;
                try {
                    sftp.cd(dir);
                } catch (SftpException ex) {
                    sftp.mkdir(dir);
                    sftp.cd(dir);
                }
            }
        }
        sftp.put(input, fileName);  //上传文件
    }


    /**
     * 下载文件。
     *
     * @param directory    下载目录
     * @param downloadFile 下载的文件
     * @param saveFile     存在本地的路径
     */
    public void download(String directory, String downloadFile, String saveFile) throws SftpException, IOException {
        if (directory != null && !"".equals(directory)) {
            sftp.cd(directory);
        }
        File file = new File(saveFile);
        if(!file.exists()) {
            //先得到文件的上级目录，并创建上级目录，在创建文件
            file.getParentFile().mkdir();
            //创建文件
            file.createNewFile();
        }
        sftp.get(downloadFile, new FileOutputStream(file));
    }

    /**
     * 下载文件。
     *
     * @param directory    下载目录
     * @param downloadFile 下载的文件
     */
    public InputStream download(String directory, String downloadFile) throws SftpException, IOException {
        if (directory != null && !"".equals(directory)) {
            sftp.cd(directory);
        }
        InputStream is = sftp.get(downloadFile);
        return is;
    }

    /**
     * 删除文件
     *
     * @param directory  要删除文件所在目录
     * @param deleteFile 要删除的文件
     */
    public void delete(String directory, String deleteFile) throws SftpException {
        sftp.cd(directory);
        sftp.rm(deleteFile);
    }


    /**
     * 列出目录下的文件
     *
     * @param directory 要列出的目录
     * @param
     */
    public Vector<?> listFiles(String directory) throws SftpException {
        return sftp.ls(directory);
    }

    //承载连接时的用户信息
    public static class MyUserInfo implements UserInfo {
        private String passphrase = null;
        public MyUserInfo(String passphrase) {
            this.passphrase = passphrase;
        }
        public String getPassphrase() {
            return passphrase;
        }
        public String getPassword() {
            return null;
        }
        public boolean promptPassphrase(String s) {
            return true;
        }
        public boolean promptPassword(String s) {
            return true;
        }
        public boolean promptYesNo(String s) {
            return true;
        }
        public void showMessage(String s) {
            System.out.println(s);
        }
    }


    //上传文件测试
    public static void main(String[] args) throws Exception {
        downloadFile("test/shijinshi","test4_sftp.jpg","c://test/test.jpg");
    }

    /**
     * 上传文件
     * @param file 文件字节
     * @param filePath 服务器路径
     * @param fileName 服务器文件名
     * @throws Exception
     */
    public static void uploadFile(byte[] file, String filePath, String fileName)  throws Exception {
        SftpUtil sftp = new SftpUtil("IMES_user",  "109.116.6.114", 22, "Tamir.jar");
        sftp.login();

        InputStream is =  new ByteArrayInputStream(file);
        sftp.upload(filePath, fileName, is);
        is.close();

        sftp.logout();
    }

    /**
     * 上传文件
     * 默认服务器路径
     * @param file 文件字节
     * @param fileName 服务器文件名
     * @throws Exception
     */
    public static void uploadFile(byte[] file, String fileName)  throws Exception {
        SftpUtil sftp = new SftpUtil("IMES_user",  "109.116.6.114", 22, "Tamir.jar");
        sftp.login();

        InputStream is =  new ByteArrayInputStream(file);
        sftp.upload(bootdoConfig.getUploadPath(), fileName, is);
        is.close();

        sftp.logout();
    }

    /**
     * 下载文件。
     *
     * @param directory    服务器目录
     * @param downloadFile 服务器文件名
     * @param saveFile     存在本地的路径
     */
    public static void downloadFile(String directory, String downloadFile, String saveFile) throws Exception {
        SftpUtil sftp = new SftpUtil("IMES_user",  "109.116.6.114", 22, "Tamir.jar");
        sftp.login();

        sftp.download(directory,downloadFile,saveFile);

        sftp.logout();
    }

    /**
     * 下载文件。
     * 默认服务器路径下载
     * @param downloadFile 服务器文件名
     * @param saveFile     存在本地的路径
     */
    public static void downloadFile(String downloadFile, String saveFile) throws Exception {
        SftpUtil sftp = new SftpUtil("IMES_user",  "109.116.6.114", 22, "Tamir.jar");
        sftp.login();

        sftp.download(bootdoConfig.getUploadPath(),downloadFile,saveFile);

        sftp.logout();
    }

    /**
     * 文件下载/预览
     */
    public static void download(HttpServletResponse response,String fileOriginName, String fileName) throws Exception {
        SftpUtil sftp = new SftpUtil("IMES_user",  "109.116.6.114", 22, "Tamir.jar");
        sftp.login();
        /*
         * 获取mimeType
         */
        String mimeType = URLConnection.guessContentTypeFromName(fileName);
        if (mimeType == null) {
            mimeType = "application/octet-stream";
        }

        response.setContentType(mimeType);
        response.setHeader("Content-disposition", String.format("attachment; filename=\"%s\"", URLEncoder.encode(fileOriginName, "UTF-8")));
        response.setCharacterEncoding("UTF-8");
        //response.setContentLength((int) file.length());
        try (InputStream is = sftp.download(bootdoConfig.getUploadPath(),fileName)){
            FileCopyUtils.copy(is, response.getOutputStream());
        }

        sftp.logout();
    }

    /**
     * 文件下载/预览
     */
    public static void preview(HttpServletResponse response,String fileOriginName, String fileName) throws Exception {
        SftpUtil sftp = new SftpUtil("IMES_user",  "109.116.6.114", 22, "Tamir.jar");
        sftp.login();
        /*
         * 获取mimeType
         */
        String mimeType = URLConnection.guessContentTypeFromName(fileOriginName);
        if (mimeType == null) {
            mimeType = "application/octet-stream";
        }

        response.setContentType(mimeType);
        response.setHeader("Content-disposition", String.format("inline; filename=\"%s\"", URLEncoder.encode(fileOriginName, "UTF-8")));
        response.setCharacterEncoding("UTF-8");
        try (InputStream is = sftp.download(bootdoConfig.getUploadPath(),fileName)){
            FileCopyUtils.copy(is, response.getOutputStream());
        }

        sftp.logout();
    }

}